#include "engine.h"
#include "mybeep.h"
#include "recordengine.h"
using namespace std;

const long engine::ID_TIMER1 = wxNewId();
const long engine::ID_TIMER2 = wxNewId();

// event table for the tab viewer
BEGIN_EVENT_TABLE(engine, wxWindow)
  EVT_TIMER   (engine::ID_TIMER1, engine::onTimer1Timer)
  EVT_TIMER   (engine::ID_TIMER2, engine::onTimer2Timer)
END_EVENT_TABLE()

engine::engine(song *theSongInit, tabView *theTabViewInit) {
  theSong = theSongInit;
  theTabView = theTabViewInit;
  timer1.SetOwner(this, ID_TIMER1);
  timer2.SetOwner(this, ID_TIMER2);
  noteNr = 0;
  countNr = 0;
  reset();
  sound = false;
}

engine::~engine() {

}

// the timer has ended for the notes
void engine::onTimer1Timer(wxTimerEvent& event) {
  if(noteNr < (int)theSong->notes.size() - 1) {
    timer1.Start((int)((float)theSong->notes[noteNr]->time / theSong->speed));
  }
  if(sound) {
    // start a myBeep thread (prevents blocking)
    myBeep* theBeep = new myBeep(theSong->notes[noteNr]->frequency, (int)((float)theSong->notes[noteNr]->time / theSong->speed));
    if(theBeep->Create() != wxTHREAD_NO_ERROR) {
        wxMessageBox(_("Can't create thread!"));
    }
    if(theBeep->Run() != wxTHREAD_NO_ERROR) {
        wxMessageBox(wxT("Can't start thread!"));
    }
    //Beep((int)(theSong->notes[noteNr]->frequency + 0.5), theSong->notes[noteNr]->time);
    //Sound((int)(theSong->notes[noteNr]->frequency + 0.5), theSong->notes[noteNr]->time, 127, 1, 111);
    //Sound(theSong->notes[noteNr]->frequency, 200, 127,111);  // 2 second blast
  } else {
    // record and analyse
    if(!theSong->notes[noteNr]->rest) {
      // record
      recordEngine *testRecordEngine = new recordEngine(theSong->notes[noteNr]->frequency, (int)(((float)theSong->notes[noteNr]->time / theSong->speed) * 0.9),
                                                        theLog, noteNr, theSong->notes[noteNr], theTabView, theGauge, 0, spnTreshold);
      if(testRecordEngine->Create() != wxTHREAD_NO_ERROR) {
        wxMessageBox(_("Can't create thread!"));
      }
      if(testRecordEngine->Run() != wxTHREAD_NO_ERROR) {
        wxMessageBox(_("Can't start thread!"));
      }
    }
  }
  noteNr++;
}

// the timer has ended for the metronome
void engine::onTimer2Timer(wxTimerEvent& event) {
  if(countNr == -1)
    onTimer1Timer(*(new wxTimerEvent()));
  // tick
  if(!sound) {
    // only play a tick when other sound is disabled
    myBeep* theBeep = new myBeep(1000, 100);
    if(theBeep->Create() != wxTHREAD_NO_ERROR) {
        wxMessageBox(_("Can't create thread!"));
    }
    if(theBeep->Run() != wxTHREAD_NO_ERROR) {
        wxMessageBox(wxT("Can't start thread!"));
    }
  }
  if(playing && noteNr < (int)theSong->notes.size()) {
    timer2.Start(countDuration);
  } else {
    stop();
  }
  countNr++;
  theTabView->doUpdate();
}

void engine::reset() {
  countDuration = (int)((float)60000 / theSong->tempo / theSong->speed);
  //countNr = -2 * (theSong->metertop);
  Update();
  playing = false;
}

// starts the loop for a song
void engine::start() {
  if(theSong->artist.Length() > 0) {
    // a song is loaded, start the timer
    for(int i = 0; i < (int)theSong->notes.size(); i++) {
      theSong->notes[i]->status = 0;
    }
    theLog->AppendText(_("Start the song\n"));
    playing = true;
    noteNr = 0;
    countNr = theSong->metertop * -1 - 1;
    onTimer2Timer(*(new wxTimerEvent()));
  } else {
    wxMessageBox(_("There is no song loaded"), _("Error"));
  }
}

void engine::stop() {
  theLog->AppendText(_("Stop the song\n"));
  playing = false;
  timer1.Stop();
  timer2.Stop();
}
